Import mojo

Import nDrawExts  'The following line is used to override SetBlend
#If TARGET="glfw"
	Alias SetBlend = SetBlend2
	Alias Cls = Cls2
#End 

Function Main:Int()
	New Game()
End Function

Class Game Extends App
	Field bg:Image, fg:Image
	Field b1:Int = BLEND_MULTIPLY   'Blend mode
	Field lop:Int  'Logic op mode
	Field swap:Int = 1 'swaps color wheels, like a bool
	
	Field blendNames:String[] =["None (Alpha blending)", "Additive", "Soft Add", "Multiply", "Inverse", "(Undefined)"]
	Field lopNames:String[] =["None", "Invert", "Invert underlying", "And", "Nand", "Or", "Nor", "Xor", "Equivalents",
							   "And (Reverse)", "And (Inverted)", "Or (Reverse)", "Or (Inverted)", "(Undefined)"]
	Field ath:Float = 0.5  'Alpha threshold for logicOps
	
	Field theta:Float, theta2:Float
	
	Method OnCreate()
		bg = LoadImage("monkey.png",, Image.MidHandle)
		fg = LoadImage("bubble.png",, Image.MidHandle)
		SetUpdateRate 60
		
	End Method
	
	Method OnUpdate()
		Local input:Int = GetChar()

		'Set blend mode
		If input >= 48 And input < 58 Then
			input -= 48
			 b1 = input
		End If
		
		'Set color wheels
		If KeyHit(KEY_SPACE) Or MouseHit(MOUSE_RIGHT) Or TouchHit(2)
			swap = 1 - swap
		End If
		
		'Cycle blends
		If MouseHit
			b1 += 1
			If b1 > 4 Then b1 = 0
		End If

		'Alpha thresholdy things
		If KeyDown(KEY_LEFT)
			ath -= 0.01
		End If

		If KeyDown(KEY_RIGHT)
			ath += 0.01
		End If
		ath = Clamp(ath, 0.0, 1.0)
		
		'LogicOp cycler
		If MouseHit(MOUSE_MIDDLE)
			If lop >= 12 Then lop = 0 Else lop += 1
		End If

		'Move the animated things around
		theta += 1
		If theta >= 360 Then theta -= 360
		theta2 += 3.231
		If theta2 >= 360 Then theta2 -= 360
				
		If KeyHit(KEY_ESCAPE) Then Error("")
	End Method
	
	Method OnRender()	
		Cls2(255 * swap, 255 * swap, 255 * swap)
		ClearStencil()

		SetAlphaThreshold(ath)

		EnableStencil()   'Everything between EnableStencil and DisableStencil is drawn inside the stencil.
		'We use DrawToStencil(True) to draw directly to the stencil. This is our last chance to set alpha threshold.
		DrawToStencil(True)
			DrawCircle(MouseX, MouseY, 124)
			'DrawImage(fg, MouseX(), MouseY(), 0, 0.5, 0.5)
		DrawToStencil(False) 'Set it back to false to enable normal drawing again.

		'Draw checkerboard
		For Local y:Int = 0 To DeviceHeight + 18 Step 36
			For Local x:Int = 0 To DeviceWidth + 18 Step 36
			SetColor(128, 128, 128); SetAlpha(0.5)
				'DrawCircle(x, y, 9)
				DrawPoly([x + 18.0, y, x, y - 18.0, x - 18.0, y, x, y + 18.0])
			SetColor(255, 255, 255); SetAlpha(1)
			Next
		Next

		DisableStencil()  'Stop the stencil operation
		
		'Draw monkey
		DrawImage(bg, DeviceWidth() / 2 + Sin(theta2) * 32, DeviceHeight() / 2 + Sin(theta) * 64)

		'Draw venn diagram
 		 SetBlend(b1)
		QColor(1 + swap * 3)
		DrawCircle(DeviceWidth() / 2 + Sin(theta) * 64, DeviceHeight() / 2 + Cos(theta) * 64, 128)
		QColor(2 + swap * 3)
		DrawCircle(DeviceWidth() / 2 + Sin(theta + 120) * 64, DeviceHeight() / 2 + Cos(theta + 120) * 64, 128)
		QColor(3 + swap * 3)
		DrawCircle(DeviceWidth() / 2 + Sin(theta + 240) * 64, DeviceHeight() / 2 + Cos(theta + 240) * 64, 128)
		QColor(7)
		 SetBlend(0)

		 
		 'Draw Some text stuff -- inverted if the bg colors have been swapped.		 
		 SetAlphaThreshold(0)  'Forces a draw of the entire surface
		 SetLogicOp(LOGICOP_COPY_INVERTED And swap)
		 DrawText("Number keys/LMB adjust the blend mode.", 8, 8)
		 DrawText("Press SPACEBAR, RMB, or 2 touches to toggle RGB/CMY colors.", 8, 20)
		 
		 DrawText("Threshold: " + ath, 8, 40)
		 
		 SetColor(255, 255, 255); SetBlend(0)
		 Local swapMode:String
		 If swap = 0 Then swapMode = "RGB" Else swapMode = "CMY"
		 DrawText("Colors: " + swapMode, 8, DeviceHeight() -36,, 1)
		 DrawText("LogicOp mode: " + lop + ", " + lopNames[lop], 8, DeviceHeight() -20,, 1)
		 DrawText("Blend mode: " + b1 + ", " + blendNames[Min(5, b1)], 8, DeviceHeight() -8,, 1)
	 	 SetLogicOp(LOGICOP_DISABLE)  'Re-setups the logicOps for next time
		 	
		 
		 'Set the logic op and alpha cull to whatever the user has selected
		SetAlphaThreshold(ath)
		SetLogicOp(lop)
			DrawImage(fg, MouseX(), MouseY(), 0, 0.5, 0.5)
			'DrawCircle(128, 128, 128)
		SetLogicOp(LOGICOP_DISABLE)

	End Method

End Class

Function QColor:Void(color:Int)
	Select color
		Case 0 'Black
		SetColor(0, 0, 0)
		Case 1 'Red
		SetColor(192, 0, 0)
		Case 2 'Green
		SetColor(0, 192, 0)
		Case 3 'Blue
		SetColor(0, 0, 192)
		Case 4 'Cyan
		SetColor(0, 192, 192)
		Case 5 'Magenta
		SetColor(192, 0, 192)
		Case 6 'Yellow
		SetColor(192, 192, 0)
		Case 7 'Gray
		SetColor(128, 128, 128)
		Case 8 'White
		SetColor(192, 192, 192)
	End Select
End Function